package com.kingsoft.dc.khaos.extender.meta.utils;

import com.alibaba.fastjson.JSONArray;
import com.kingsoft.dc.khaos.extender.exception.MetaException;
import com.kingsoft.dc.khaos.extender.meta.api.*;
import com.kingsoft.dc.khaos.extender.meta.model.TenantInfo;
import org.eclipse.jetty.util.ajax.JSON;

import java.lang.reflect.InvocationTargetException;

/**
 * Created by jing on 19/6/25.
 */
public class DmMetaUtils {
    private static String GET_DATASOURCE = "getDatasource";
    private static String GET_DATABASE = "getDatabase";
    private static String GET_TABLE = "getTable";
    private static String GET_COLUMNS = "getColumns";
    private static String CHECK_AUTH = "getProjectAuth";
    private static String GET_DATASOURCE_LIST = "getDatasourceList";
    private static String GET_DATASOURCE_BY_ID = "getDatasourceById";
    private static String GET_ES_CHECK_INFO = "getESCheckInfo";
    private static String GET_MQ_CHECK_INFO = "getMQCheckInfo";
    private static String GET_CHECK_RULE = "getCheckRule";
    private static String GET_DESIGN_CHECK_RULE = "getDesignCheckRule";//getDesignCheckRule
    private static String GET_TABLESPLIT = "getTableSplit";
    private static String GET_REALTABLE = "getRealTable";
    private static String GET_REALTABLE_WITH_DATETIME_AND_WRITE = "getRealTableWithDateTimeAndWrite";
    private static String GET_UNMANAGEDDATASOURCE = "getUnmanagedDatasource";
    private static String REPORTDATASTATUS = "reportDataStatus";
    private static String GET_DATASOURCE_BY_NAME = "getDatasourceByName";
    private static String GET_TABLE_PARTITIONS = "getTablePartitions";

    public static <T> T convertClass(Object obj, Class<T> tClass) {
        return (T) obj;
    }

    public static <T> T callMethod(String className, String methodName, DmRequest request, Class<T> tClass) {
        Class clazz = null;
        try {
            clazz = Class.forName(className);
            Object ds = clazz.getMethod(methodName, DmRequest.class).invoke(clazz.newInstance(), new Object[]{request});
            return convertClass(ds, tClass);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            throw new MetaException(e.getMessage());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> T callMethod(String className, String methodName, DmRequest request) {
        Class clazz = null;
        try {
            clazz = Class.forName(className);
            Object ds = clazz.getMethod(methodName, DmRequest.class).invoke(clazz.newInstance(), new Object[]{request});
            return (T)ds;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据数据源ID获取数据源地址
     * request参数构建
     * 方法1:构建params字符串参数:request.setParams("{\"env\":\"TEST\":\"dbName\":\"db1\",\"tblName\":\"tab1\",\"privilege\":\"read\"}
     * 方法2:构建MetaParams实体类参数
     *   MetaParams metaParams = new MetaParams();
     *   metaParams.buildReadDatasourceParams(run_env, projectId, dbName, tblName);
     *   request.setMetaParams(metaParams);
     * @param request
     * @return
     */
    public static <T> T getDatasource(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_DATASOURCE, request, tClass);
    }

    public static <T> T getDatasourceList(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_DATASOURCE_LIST, request, tClass);
    }

    public static <T> T getDatabase(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_DATABASE, request, tClass);
    }


    public static <T> T getTable(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_TABLE, request, tClass);
    }

    public static <T> T getColumns(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_COLUMNS, request, tClass);
    }

    public static <T> T checkProjectAuth(String className, DmRequest request, Class<T> tClass) {
        Object obj = JSONArray.toJSON(request);
        String json = obj.toString();
        System.out.println("DmRequest:"+ json);
        return callMethod(className, CHECK_AUTH, request, tClass);
    }

    public static TenantInfo getTenantAkSk(DmRequest request) {
        TenantInfo tenantInfo = DmApiUtils.getTenantAkSk(request);
        return tenantInfo;
    }

    public static <T> T getTableSplit(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_TABLESPLIT, request, tClass);
    }

    public static <T> T getRealTable(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_REALTABLE, request, tClass);

    }

    public static <T> T getRealTableWithDateTimeAndWrite(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_REALTABLE_WITH_DATETIME_AND_WRITE, request, tClass);

    }

    public static <T> T getUnmanagedDatasource(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_UNMANAGEDDATASOURCE, request, tClass);
    }

    public static <T> T reportDataStatus(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, REPORTDATASTATUS, request, tClass);
    }

    public static <T> T getTablePartitons(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_TABLE_PARTITIONS, request, tClass);
    }
    /**
     * 根据数据源ID获取数据源地址
     * request参数构建
     * 方法1:request.setParams("{\"env\":\"TEST\":\"dsIds\":[1],\"privilege\":\"read\"}
     * 方法2:
     *   MetaParams metaParams = new MetaParams();
     *   metaParams.buildReadDatasourceParams(run_env, dsId);
     *   request.setMetaParams(metaParams);
     * @param request
     * @return
     */
    public static <T> T getDatasourceById(String className, DmRequest request) {
        return callMethod(className, GET_DATASOURCE_BY_ID, request);
    }

    public static <T> T getCheckRule(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_CHECK_RULE, request, tClass);
    }

    //getDesignCheckRule
    public static <T> T getDesignCheckRule(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_DESIGN_CHECK_RULE, request, tClass);
    }

    public static <T> T getESCheckInfo(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_ES_CHECK_INFO, request, tClass);
    }

    public static <T> T getMQCheckInfo(String className, DmRequest request, Class<T> tClass) {
        return callMethod(className, GET_MQ_CHECK_INFO, request, tClass);
    }

    /**
     * 根据数据源NAME获取数据源地址
     * request参数构建
     * 方法1:request.setParams("{\"env\":\"TEST\":\"dsNames\":[1],\"privilege\":\"read\"}
     * 方法2:
     *   MetaParams metaParams = new MetaParams();
     *   metaParams.buildReadDatasourceParams(run_env, dsId);
     *   request.setMetaParams(metaParams);
     * @param request
     * @return
     */
    public static <T> T getDatasourceByName(String className, DmRequest request) {
        return callMethod(className, GET_DATASOURCE_BY_NAME, request);
    }
}
